package com.jing.yao.security;

import com.jing.yao.security.handler.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

/**
 * security 安全配置
 *
 * @author lirui
 * @since 2020-06-13
 */
@Configuration
@EnableGlobalMethodSecurity(jsr250Enabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {


    @Autowired
    private JwtTokenAuthenticationFilter jwtTokenAuthenticationFilter;

    /**
     * 自定义，从数据库获取用户信息
     *
     * @return
     */
    @Bean
    public UserDetailsService apUserDetailsService() {
        return new YaoUserDetailsService();
    }


    /**
     * 自定义userDetailService
     *
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(apUserDetailsService())
                .passwordEncoder(new BCryptPasswordEncoder());
    }

    /**
     * 未登录
     *
     * @return
     */
    @Bean
    public AccessDeniedHandler accessDeniedHandler() {
        return new YaoAccessDeniedHandler();
    }

    /**
     * 权限校验未通过处理
     *
     * @return
     */
    @Bean
    public AuthenticationEntryPoint authenticationEntryPoint() {
        return new YaoAuthenticationEntryPoint();
    }

    /**
     * 登录成功处理
     *
     * @return
     */
    @Bean
    public YaoLoginSuccessHandler customLoginSuccessHandler() {
        return new YaoLoginSuccessHandler();
    }

    /**
     * 登录失败处理
     *
     * @return
     */
    @Bean
    public YaoLoginFailureHandler customLoginFailureHandler() {
        return new YaoLoginFailureHandler();
    }

    /**
     * 登出成功处理
     *
     * @return
     */
    @Bean
    public YaoLogoutSuccessHandler customLogoutSuccessHandler() {
        return new YaoLogoutSuccessHandler();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.exceptionHandling()
                .accessDeniedHandler(accessDeniedHandler())
                .authenticationEntryPoint(authenticationEntryPoint())
                .and()
                .csrf().disable()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authorizeRequests()
                .antMatchers("/login", "/logout", "/health").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin().successHandler(customLoginSuccessHandler())
                .failureHandler(customLoginFailureHandler())
                .and()
                .logout().logoutSuccessHandler(customLogoutSuccessHandler());

        http.addFilterBefore(
                new YaoUsernamePasswordAuthenticationFilter(this.authenticationManager(), customLoginSuccessHandler(),
                        customLoginFailureHandler()),
                UsernamePasswordAuthenticationFilter.class);
        http.addFilterBefore(jwtTokenAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
    }
}
